//
//  Messaging.m
//  iCan - iPhone Context-Aware Navigation
//  Carnegie Mellon University - 18-842 Distributed Systems
//
//  Created by Andrew Santell on 3/26/12.
//  Copyright (c) 2012 Andrew Santell. All rights reserved.

#import "Messaging.h"
#import "iCanAppDelegate.h"
#import "MsgDetails.h"
#import "iCanViewController.h"

@interface Messaging ()

@end

@implementation Messaging
@synthesize recipients, messageData;
@synthesize result, message, badCookie;
@synthesize appDelegate, spinner, details;
@synthesize inputStream, outputStream;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	appDelegate = [[UIApplication sharedApplication] delegate];
    badCookie = FALSE;
}

- (void)viewDidUnload
{
    [self setRecipients:nil];
    [self setMessageData:nil];
    [self setResult:nil];
    [self setMessage:nil];
    [self setAppDelegate:nil];
    [self setSpinner:nil];
    [self setDetails:nil];
    [self setInputStream:nil];
    [self setOutputStream:nil];
    
    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


- (IBAction)sendMessage:(id)sender 
{
    NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789, "];
    BOOL validRecipients = [[recipients.text stringByTrimmingCharactersInSet:set] isEqualToString:@""];
    
    if ((messageData.text.length < 300) && (validRecipients == TRUE) && (recipients.text.length < 300))
    {
        /* Load spinner on top of screen until receiving network result */
        spinner = [[SpinnerView alloc] init];
        [spinner loadSpinnerIntoView:self.view];

        NSString *sanitizedMessage = [messageData.text stringByReplacingOccurrencesOfString:@";" withString:@"%42"];
        NSString *sanitizedRecipients = [recipients.text stringByReplacingOccurrencesOfString:@" " withString:@""];
        
        /*Populate message to send to server */
        message = @"send_message";
        message = [message stringByAppendingString:@";"];
        message = [message stringByAppendingString:appDelegate.myName];
        message = [message stringByAppendingString:@";"];
        message = [message stringByAppendingString:appDelegate.myCookie];
        message = [message stringByAppendingString:@";"];
        message = [message stringByAppendingString:sanitizedRecipients];
        message = [message stringByAppendingString:@";"];
        message = [message stringByAppendingString:sanitizedMessage];
        message = [message stringByAppendingString:@";"];
        message = [message stringByAppendingString:@"\n"];

        /* Disable Back button while connecting to network */
        self.navigationController.navigationBar.userInteractionEnabled = NO;

        /* Initiate network connection */
        [self initNetworkCommunication];
    }
    
    else if (messageData.text.length >= 300)
    {
        UIAlertView *lenAlert = [[UIAlertView alloc] initWithTitle:@"Max Length Exceeded" message:@"Please enter a message less than 300 characters"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];   
        [lenAlert show];
    }
    else if (recipients.text.length >= 300)
    {
        UIAlertView *lenAlert = [[UIAlertView alloc] initWithTitle:@"Max Length Exceeded" message:@"Please enter fewer recipients"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];   
        [lenAlert show];
    }
    else if (validRecipients == FALSE)
    {
        UIAlertView *recAlert = [[UIAlertView alloc] initWithTitle:@"Invalid Characters" message:@"Please enter valid recipients"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];   
        [recAlert show];
    }
    
}

- (void) analyzeResult
{
 	/* Set up alerts */
    UIAlertView *badAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"You received an error from the network"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    UIAlertView *goodAlert = [[UIAlertView alloc] initWithTitle:@"Success!" message:@"Your message was successfully sent"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    UIAlertView *badCookieAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Your session has expired.  Please login again"delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    UIAlertView *invalidUserAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Invalid users."delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

    NSLog(@"result = %@", result);
    
    
    if ([result isEqualToString:@"ACK"])
    { 
        NSLog(@"Message Sent");
        [goodAlert show];
    }
    else if ([result isEqualToString:@"NACK"])
    { 
        NSLog(@"Error with received data");
        [badAlert show];
    }
    else if ([result isEqualToString:@"BAD_COOKIE"])
    { 
        NSLog(@"Bad Cookie");
        badCookie = TRUE;
        [badCookieAlert show];
    }
    else if ([result isEqualToString:@"INVALID"])
    { 
        [invalidUserAlert show];
        NSLog(@"invalid user");
    }
 
    result = NULL; 
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex   
{
    if (badCookie == TRUE)
    {
        badCookie = FALSE;
        result = NULL;
        iCanViewController *mainScreen = [self.storyboard instantiateViewControllerWithIdentifier:@"MainScreen"];
        [self presentViewController:mainScreen animated:YES completion:nil];
    }
}


/* Initiate network connection */
- (void) initNetworkCommunication
{
    CFReadStreamRef readStream = NULL;
    CFWriteStreamRef writeStream = NULL;
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef) appDelegate.nodeIP, appDelegate.nodePort, &readStream, &writeStream);
    
    inputStream = (__bridge NSInputStream *) readStream;
    outputStream = (__bridge NSOutputStream *) writeStream;
    
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    
    /* Put input and output streams into a run loop */
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    [inputStream open];
    [outputStream open];
    
    /* Put message into a format that can be sent across the network (NSData) */
    NSData *data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSASCIIStringEncoding]];
    
    /* Send message to network */
    [outputStream write:[data bytes] maxLength:[data length]];
    
    
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent 
{
    /* Create error popup for failed connections */
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not connect to host"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    
    switch (streamEvent) 
    {
		case NSStreamEventOpenCompleted:
			NSLog(@"Stream opened");
			break;
            
        /* Accept return message from network */
		case NSStreamEventHasBytesAvailable:
            
            if (theStream == inputStream) 
            {
                
                uint8_t buffer[1024];
                int len;
                
                while ([inputStream hasBytesAvailable]) 
                {
                    len = [inputStream read:buffer maxLength:sizeof(buffer)];
                    if (len > 0) 
                    {
                        
                        result = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
                        
                        if (nil != result) 
                        {
                            NSLog(@"Response: %@", result);
                        }
                    }
                }
            }
			break;			
            
		case NSStreamEventErrorOccurred:
            
            NSLog(@"Can not connect to the host!");
            NSLog(@"Error Result (Should be NULL) = %@", result);
            [inputStream close];
            [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream close];
            [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [spinner removeSpinner];
            [alert show];
            /* Enable Back Button again */
            self.navigationController.navigationBar.userInteractionEnabled = YES;
			break;
            
		case NSStreamEventEndEncountered:
            NSLog(@"Closing Connection");
            [inputStream close];
            [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream close];
            [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            self.navigationController.navigationBar.userInteractionEnabled = YES;
            [spinner removeSpinner];
            [self analyzeResult];
			break;
            
		case NSStreamEventHasSpaceAvailable:
            NSLog (@"Output Buffer is Empty");
            break;
            
        default:
			NSLog(@"Unknown event");
            NSLog(@"Error Result (Should be NULL) = %@", result);
            [inputStream close];
            [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream close];
            [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [spinner removeSpinner];
            self.navigationController.navigationBar.userInteractionEnabled = YES;
            [alert show];
	}
}

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
{
    [theTextField resignFirstResponder];
    return YES;
}

- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if([text isEqualToString:@"\n"])
    {
        [textView resignFirstResponder];
        return NO;
    }
    
    return YES;
}

@end
